/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package runebound.factorias;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import runebound.modelo.heores.experiencia.Atributo;
import runebound.modelo.monstruos.Monstruo;
import runebound.modelo.monstruos.comportamientos.AntesCombateAccion;
import runebound.modelo.monstruos.comportamientos.AntesCombateTestAgota;
import runebound.modelo.monstruos.comportamientos.AntesCombateTestHit;
import runebound.modelo.monstruos.comportamientos.AntesCombateTestSetAtributo;
import runebound.modelo.monstruos.comportamientos.AntesDeCombate;
import runebound.modelo.Habilidad;
import runebound.modelo.TipoAmenaza;
import runebound.modelo.monstruos.comportamientos.RecompensaOro;

/**
 *
 * @author malopez
 */
public class MonstruoFactoria {
    
    private static final MonstruoFactoria instance = new MonstruoFactoria();
    private static final String RECOMPENSA_NADA = "NADA";
    private static final String HACER_NADA = "LIBRE";
    private static final String OBJETIVO_MONSTRUO = "MONST";
    private static final String SEPARADOR_TOKENS = "_";

    public static MonstruoFactoria getInstance() {
        return instance;
    }
    
    public Monstruo createMonstruo(ResultSet resultSet) throws SQLException{
        
        Monstruo m = new Monstruo();
        m.setTitulo(resultSet.getString("titulo"));
        m.setDescripcion(resultSet.getString("descripcion"));
        m.setValorFisico(resultSet.getInt("fisico"));
        m.setValorMente(resultSet.getInt("mente"));
        m.setValorMagia(resultSet.getInt("magia"));
        m.setFuerzaFisico(resultSet.getInt("fuerzaFisico"));
        m.setFuerzaMente(resultSet.getInt("fuerzaMente"));
        m.setFuerzaMagia(resultSet.getInt("fuerzaMagia"));
        m.setVida(resultSet.getInt("vida"));
        //TODO RECOMPENSA
        this.crearRecompensa(m, resultSet.getString("recompensa"));
        //TODO ANTES DE COMBATE
        this.crearAntesDeCombate(m,resultSet.getString("antesCombate"));
        
        //Tipo de amenza
        m.setTipoAmenaza(TipoAmenaza.valueOf(resultSet.getString("tipoAmenaza")));
        return m;
    }

    private void crearRecompensa(Monstruo m, String string) {
        if(!string.equalsIgnoreCase(RECOMPENSA_NADA)){
            StringTokenizer stringTokenizer = new StringTokenizer(string, SEPARADOR_TOKENS);
            String cabecera = stringTokenizer.nextToken();
            if(cabecera.equalsIgnoreCase("ORO")){
                m.setRecompensa(new RecompensaOro(Integer.parseInt(stringTokenizer.nextToken())));
            }/* TODO Otras recompensas */
        }
    }
    

    private void crearAntesDeCombate(Monstruo m, String string) {
        StringTokenizer stringTokenizer = new StringTokenizer(string, SEPARADOR_TOKENS);
        String cabecera = stringTokenizer.nextToken();
        if(cabecera.equalsIgnoreCase("TEST")){
            try{
                antesCombateTest(stringTokenizer, m);   
            }catch(Exception e){
                Logger.getLogger(MonstruoFactoria.class.getName()).log(Level.SEVERE, "CAD:"+string, e);
                throw e;
            }
        }
        /* Antes de combate que no es una test de habilidad */
        
    }

    /**
     * El antes de combate es de tipo TEST y procesamos su descripción
     * @param stringTokenizer
     * @param m
     * @throws NumberFormatException 
     */
    private void antesCombateTest(StringTokenizer stringTokenizer, Monstruo m) throws NumberFormatException {
        /* Prueba de test antes de combate */
        
        Habilidad habilidad = Habilidad.valueOf(stringTokenizer.nextToken());
        int value = Integer.parseInt(stringTokenizer.nextToken());
        String nextToken = stringTokenizer.nextToken();
        boolean objetivoExitoMonstruo = false;
        boolean objetivoFalloMonstruo = false;
        AntesCombateAccion accionExito = AntesCombateAccion.NADA;
        AntesCombateAccion accionFallo =AntesCombateAccion.NADA;
        boolean hacerExito = false;
        boolean hacerFallo = false;
        int valorAccionExito = 0;
        int valorAccionFallo = 0;
        Atributo atributoExito=Atributo.VIDA;
        Atributo atributoFallo=Atributo.VIDA;
        
        /* Procesamos el fallo del test */
        if(nextToken.equalsIgnoreCase(HACER_NADA)){
            hacerFallo= false;
        }else{
            /* Procesamos la acción del test */
            hacerFallo = true;
            if(nextToken.equalsIgnoreCase(OBJETIVO_MONSTRUO)){
                objetivoFalloMonstruo=true;
                nextToken = stringTokenizer.nextToken();
            }
            /* Accion SET, UP, AGOTA, HIT */
            accionFallo = AntesCombateAccion.valueOf(nextToken);
            nextToken = stringTokenizer.nextToken();
            if (accionFallo==AntesCombateAccion.SET){
                atributoFallo = Atributo.valueOf(nextToken);
                nextToken = stringTokenizer.nextToken();
            }
            valorAccionFallo = Integer.parseInt(nextToken);
        }
        
        /* Procesamos el exito del test */
        if(stringTokenizer.hasMoreTokens()){
            nextToken = stringTokenizer.nextToken();
            if(nextToken.equalsIgnoreCase(HACER_NADA)){
                hacerExito = false;
            }else{
                /* Procesamos la acción del test */
                hacerExito = true;
                if(nextToken.equalsIgnoreCase(OBJETIVO_MONSTRUO)){
                    objetivoExitoMonstruo=true;
                    nextToken = stringTokenizer.nextToken();
                }
                /* Accion SET, UP, AGOTA, HIT */
                accionExito = AntesCombateAccion.valueOf(nextToken);
                nextToken = stringTokenizer.nextToken();
                if(accionExito==AntesCombateAccion.SET){
                    atributoExito = Atributo.valueOf(nextToken);
                    nextToken = stringTokenizer.nextToken();
                }
                valorAccionExito = Integer.parseInt(nextToken);
            }
        }
        AntesDeCombate antesCombate = null;
        if((hacerExito && accionExito==AntesCombateAccion.SET) ||
                (hacerFallo && accionFallo==AntesCombateAccion.SET) ){
                antesCombate = new AntesCombateTestSetAtributo(habilidad,
                value,
                objetivoExitoMonstruo,
                objetivoFalloMonstruo,
                hacerExito,
                hacerFallo, atributoExito,atributoFallo,valorAccionExito,valorAccionFallo);
        }
        
        if((hacerExito && accionExito==AntesCombateAccion.HIT) ||
                (hacerFallo && accionFallo==AntesCombateAccion.HIT) ){
                antesCombate = new AntesCombateTestHit(habilidad,
                value,
                objetivoExitoMonstruo,
                objetivoFalloMonstruo,
                hacerExito,
                hacerFallo, atributoFallo,atributoExito,valorAccionExito,valorAccionFallo);
        }
        
        if((hacerExito && accionExito==AntesCombateAccion.AGOTA) ||
                (hacerFallo && accionFallo==AntesCombateAccion.AGOTA) ){
                antesCombate = new AntesCombateTestAgota(habilidad,
                value,
                objetivoExitoMonstruo,
                objetivoFalloMonstruo,
                hacerExito,
                hacerFallo, atributoFallo,atributoExito,valorAccionExito,valorAccionFallo);
        }
        
        
        
        m.setAntesDeCombate(antesCombate);
    }
    
    
}
